////////////////////////////employees.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#include "employees.h"

/* 职工表节点定义 */
struct employees_node
{
    //======Begin======
    struct employee e;           // 职工数据
    struct employees_node *next; // 指向下一个节点
    //=======End=======
};

/* 职工表结构定义 */
struct employees
{
    //======Begin======
    struct employees_node *head; // 链表头节点
    int count;                   // 记录数量
    //=======End=======
};

/* 创建职工表 */
struct employees *employees_create()
{
    //======Begin======
    struct employees *ret = NULL;

    ret = (struct employees *)malloc(sizeof(*ret));
    if (ret == NULL)
        return NULL;

    ret->head = NULL;
    ret->count = 0;

    // 创建头节点（哨兵节点）
    ret->head = (struct employees_node *)malloc(sizeof(*ret->head));
    if (ret->head == NULL)
    {
        free(ret);
        return NULL;
    }

    ret->head->next = NULL; // 初始化空链表
    return ret;
    //=======End=======
}

/* 销毁职工表
 * @param es 要销毁的职工表指针 */
void employees_destroy(struct employees *es)
{
    //======Begin======
    assert(es != NULL);
    assert(es->head != NULL);

    // 先删除所有记录
    employees_remove_all(es);

    // 释放头节点和表结构
    free(es->head);
    free(es);
    return;
    //=======End=======
}

/* 从文件读取数据
 * @param es 职工表指针
 * @param filename 文件名
 * @return 0成功，1失败 */
int employees_read_from_file(struct employees *es, const char *filename)
{
    //======Begin======
    struct employee e;
    FILE *fp = NULL;

    fp = fopen(filename, "rb");
    if (fp == NULL)
        return 1; // 文件打开失败

    // 读取文件直到结束
    while (fread(&e, sizeof(e), 1, fp) == 1)
    {
        struct employees_node *node = NULL;
        struct employees_node *p = NULL;

        // 创建新节点
        node = (struct employees_node *)malloc(sizeof(*node));
        if (node == NULL)
        {
            perror("malloc failed in employees_read_file()");
            exit(EXIT_FAILURE);
        }

        node->next = NULL;
        node->e = e; // 复制数据

        // 找到链表末尾
        p = es->head;
        while (p && p->next != NULL)
        {
            p = p->next;
        }

        // 插入新节点
        p->next = node;
    }

    fclose(fp);
    return 0;
    //=======End=======
}

/* 保存数据到文件
 * @param es 职工表指针
 * @param filename 文件名
 * @return 0成功，1失败 */
int employees_save_to_file(struct employees *es, const char *filename)
{
    //======Begin======
    struct employees_node *p = NULL;
    FILE *fp = NULL;

    assert(es != NULL);
    assert(es->head != NULL);
    assert(filename != NULL);

    fp = fopen(filename, "wb");
    if (fp == NULL)
        return 1; // 文件打开失败

    // 遍历链表并写入文件
    p = es->head->next;
    while (p != NULL)
    {
        fwrite(&p->e, sizeof(p->e), 1, fp);
        p = p->next;
    }

    fclose(fp);
    return 0;
    //=======End=======
}

/* 添加新职工记录
 * @param es 职工表指针
 * @param e 要添加的职工记录 */
void employees_add(struct employees *es, struct employee e)
{
    //======Begin======
    struct employees_node *node = NULL;
    struct employees_node *p = NULL;

    // 创建新节点
    node = (struct employees_node *)malloc(sizeof(*node));
    if (node == NULL)
    {
        perror("malloc failed in employees_add()");
        exit(EXIT_FAILURE);
    }

    node->e = e;
    node->next = NULL;

    // 找到链表末尾
    p = es->head;
    while (p && p->next != NULL)
    {
        p = p->next;
    }

    // 插入新节点
    p->next = node;
    es->count++;
    return;
    //=======End=======
}

/* 打印所有职工记录
 * @param es 职工表指针 */
void employees_print(struct employees *es)
{
    //======Begin======
    struct employees_node *p = NULL;

    p = es->head->next;

    if (p == NULL)
    {
        printf("职工表为空\n");
        return;
    }

    // 遍历并打印所有记录
    while (p != NULL)
    {
        printf("职工号：%s，姓名：%s，部门号：%s，工资：%.2f\n",
               p->e.no, p->e.name, p->e.depno, p->e.salary);
        p = p->next;
    }
    return;
    //=======End=======
}

/* 交换两个职工记录
 * @param a 第一条记录指针
 * @param b 第二条记录指针 */
void swap(struct employee *a, struct employee *b)
{
    //======Begin======
    struct employee temp = *a;
    *a = *b;
    *b = temp;
    return;
    //=======End=======
}

/* 按职工号冒泡排序
 * @param es 职工表指针 */
void employees_sort_by_no(struct employees *es)
{
    //======Begin======
    int swapped; // 交换标志
    struct employees_node *ptr1;
    struct employees_node *lptr = NULL; // 上次排序结束位置

    if (es->head->next == NULL)
        return; // 空表检查

    do
    {
        swapped = 0;
        ptr1 = es->head->next;

        // 遍历未排序部分
        while (ptr1->next != lptr)
        {
            // 比较职工号
            if (strcmp(ptr1->e.no, ptr1->next->e.no) > 0)
            {
                swap(&ptr1->e, &ptr1->next->e); // 交换数据
                swapped = 1;
            }
            ptr1 = ptr1->next;
        }
        lptr = ptr1; // 更新已排序边界
    } while (swapped);
    //=======End=======
}

/* 按部门号冒泡排序
 * @param es 职工表指针 */
void employees_sort_by_depno(struct employees *es)
{
    //======Begin======
    int swapped;
    struct employees_node *ptr1;
    struct employees_node *lptr = NULL;

    if (es->head->next == NULL)
        return;

    do
    {
        swapped = 0;
        ptr1 = es->head->next;

        while (ptr1->next != lptr)
        {
            if (strcmp(ptr1->e.depno, ptr1->next->e.depno) > 0)
            {
                swap(&ptr1->e, &ptr1->next->e);
                swapped = 1;
            }
            ptr1 = ptr1->next;
        }
        lptr = ptr1;
    } while (swapped);
    //=======End=======
}

/* 按工资冒泡排序
 * @param es 职工表指针 */
void employees_sort_by_salary(struct employees *es)
{
    //======Begin======
    int swapped;
    struct employees_node *ptr1;
    struct employees_node *lptr = NULL;

    if (es->head->next == NULL)
        return;

    do
    {
        swapped = 0;
        ptr1 = es->head->next;

        while (ptr1->next != lptr)
        {
            if (ptr1->e.salary > ptr1->next->e.salary)
            {
                swap(&ptr1->e, &ptr1->next->e);
                swapped = 1;
            }
            ptr1 = ptr1->next;
        }
        lptr = ptr1;
    } while (swapped);
    //=======End=======
}

/* 删除指定职工号记录
 * @param es 职工表指针
 * @param no 要删除的职工号 */
void employees_remove_by_no(struct employees *es, const char *no)
{
    //======Begin======
    struct employees_node *p = NULL;

    p = es->head; // 从头节点的下一个开始查找
    while (p && p->next != NULL)
    {
        // 找到匹配的职工号
        if (strcmp(p->next->e.no, no) == 0)
        {
            struct employees_node *node = NULL;

            node = p->next;       // 保存要删除的节点
            p->next = node->next; // 从链表移除
            free(node);           // 释放内存
            es->count--;          // 更新计数

            printf("职工号为 %s 的记录已删除。\n", no);
            return;
        }
        p = p->next; // 继续查找
    }
    printf("未找到职工号为 %s 的记录。\n", no);
    return;
    //=======End=======
}

/* 删除所有记录
 * @param es 职工表指针 */
void employees_remove_all(struct employees *es)
{
    //======Begin======
    struct employees_node *node = NULL;

    // 循环释放所有节点
    while (es->head->next != NULL)
    {
        node = es->head->next;       // 获取第一个数据节点
        es->head->next = node->next; // 更新头节点指针
        free(node);                  // 释放节点内存
        es->count--;                 // 更新计数
    }
    return;
    //=======End=======
}